package com.hruiworks.campusgroup.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hruiworks.campusgroup.dao.mapper.UserMapper;
import com.hruiworks.campusgroup.enums.ErrorCode;
import com.hruiworks.campusgroup.exception.BusinessException;
import com.hruiworks.campusgroup.pojo.entity.User;
import com.hruiworks.campusgroup.pojo.request.UserUpdateRequest;
import com.hruiworks.campusgroup.pojo.vo.UserInfoVo;
import com.hruiworks.campusgroup.service.UserService;
import com.hruiworks.campusgroup.utils.OssUtils;
import com.hruiworks.usercheck.pojo.entity.JwtEntity;
import com.hruiworks.usercheck.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.UUID;

import static com.hruiworks.campusgroup.constants.UserConstant.AVATAR_DIR;
import static com.hruiworks.campusgroup.enums.ErrorCode.OTHER_ERROR;
import static com.hruiworks.campusgroup.enums.ErrorCode.PARAMS_ERROR;
import static com.hruiworks.usercheck.enums.MessageDigestAlgorithmEnum.SHA256;

/**
 * @author jiushui
 * @description 针对表【user(用户信息表)】的数据库操作Service实现
 * @createDate 2025-02-09 09:45:00
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    // 加盐
    private static final String SALT = "dDWw&UxnlOxcbl[qzr34,mx102xb=1";

    @Resource
    private UserMapper userMapper;

    @Override
    public Long userRegister(String username, String password, String checkPassword, String university) {
        // 1. 校验参数是否有空值
        if (ParamUtils.isAnyBlank(username, password, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        // 2. 校验用户名是否合法(只允许数字、字母、下划线)
        if (!UsernameUtils.onlyNumLetterUnderscore(username)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户名只允许数字、字母、下划线");
        }
        // 3. 校验用户名长度是否合法
        if (!StringUtils.strLengthBetween(username, 4, 20)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户名应该在4位(含)和20位(含)之间");
        }
        // 4. 校验两次输入的密码是否相同
        if (!PasswordUtils.comparePassword(password, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次密码不相同");
        }

        // 5. 密码加密
        String encryptedPassword = PasswordUtils.encryptPassword(password, SALT, SHA256);

        // 6. 查看用户名是否重复
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        Long count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
        }

        // 7. 插入数据
        User user = new User();
        user.setUsername(username);
        user.setPassword(encryptedPassword);
        user.setUniversity(university);
        int insert = userMapper.insert(user);

        if (insert != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR, "检查数据库日志");
        }

        return user.getId();
    }

    @Override
    public JwtEntity userLogin(String username, String password) {
        // 1. 校验参数是否有空值
        if (ParamUtils.isAnyBlank(username, password)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }

        // 2. 密码加密，之后用于比较
        String encryptedPassword = PasswordUtils.encryptPassword(password, SALT, SHA256);

        // 3. 查询数据库
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User user = userMapper.selectOne(queryWrapper);

        // 4 校验用户密码
        if (Objects.isNull(user) || !PasswordUtils.comparePassword(encryptedPassword, user.getPassword())) {
            log.info("login failed, user is not exited or wrong password");
            throw new BusinessException(ErrorCode.NULL_ERROR, "用户不存在或密码错误");
        }

        // 5 生成jwt
        User jwtUser = new User();
        jwtUser.setId(user.getId());
        jwtUser.setUsername(user.getUsername());
        jwtUser.setUserStatus(user.getUserStatus());
        jwtUser.setRole(user.getRole());
        jwtUser.setUniversity(user.getUniversity());

        return JwtUtils.generateHs256Jwt(jwtUser, 1, ChronoUnit.WEEKS);

    }

    @Override
    public UserInfoVo currentUserInfo(Long userId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getId, userId);
        User user = userMapper.selectOne(queryWrapper);
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(user, userInfoVo);
        return userInfoVo;
    }

    @Override
    public Integer updateUser(UserUpdateRequest userUpdateRequest, Long userId) {
        ParamUtils.toNull(userUpdateRequest);
        User user = new User();
        BeanUtils.copyProperties(userUpdateRequest, user);

        user.setId(userId);
        // 1. 更改密码要加密
        if (org.apache.commons.lang3.StringUtils.isNotBlank(userUpdateRequest.getPassword())) {
            user.setPassword(PasswordUtils.encryptPassword(userUpdateRequest.getPassword(), SALT, SHA256));
        }
        // 2. 更改昵称校验长度
        if (org.apache.commons.lang3.StringUtils.isNotBlank(userUpdateRequest.getNickname())) {
            if (!StringUtils.strLengthLTE(userUpdateRequest.getNickname(), 10)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "昵称长度应该不大于10");
            }
        }
        // 3. 更改邮箱校验邮箱
        if (org.apache.commons.lang3.StringUtils.isNotBlank(userUpdateRequest.getEmail())) {
            if (!EmailUtils.isIllegalEmail(userUpdateRequest.getEmail())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱地址不合法");
            }
        }

        // 4. 更改手机号码校验手机号
        if (org.apache.commons.lang3.StringUtils.isNotBlank(userUpdateRequest.getPhone())) {
            if (!PhoneNumberUtils.isIllegalChinaPhoneNumber(userUpdateRequest.getPhone())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "手机号码不合法");
            }
        }

        return userMapper.updateById(user);
    }


    @Override
    public boolean deleteUserById(Long id) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getId, id);
        int delete = userMapper.delete(queryWrapper);
        return delete == 1;
    }

    @Override
    public boolean updateUserAvatar(MultipartFile avatar, Long userId) {
        // 确保文件信息唯一
        String originalFilename = avatar.getOriginalFilename();
        String wholeDir = AVATAR_DIR+"/"+userId;

        String extname;
        if (originalFilename != null) {
            extname = originalFilename.substring(originalFilename.lastIndexOf("."));
        } else {
            throw new BusinessException(PARAMS_ERROR, "文件传入失败");
        }

        // 上传Oss
        String newFilename = UUID.randomUUID() + extname;
        try {
            OssUtils.deleteDir(wholeDir);
            OssUtils.upload(avatar,wholeDir,newFilename);
        } catch (Exception e) {
            throw new BusinessException(OTHER_ERROR, "Oss报错！！！");
        }

        // 更新数据库信息
        User user = new User();
        user.setId(userId);
        user.setAvatarUrl(OssUtils.fileUrl(wholeDir, newFilename));
        int i = userMapper.updateById(user);
        if (i != 1) {
            throw new BusinessException(OTHER_ERROR, "数据库插入出错");
        }
        return true;
    }

    // --不允许出现普通户的controller-------------------------------------------------------------------------------
}




